﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Watermark_WPF
{
    public class WatermarkCanvas : Canvas
    {
        const string DEFAULT_TEXT = "I am watermark";
        const double DEFAULT_FONT_SIZE = 14;
        const double DEFAULT_ROTATE_ANGLE = -20;
        const string DEFAULT_FONT_FAMILY = "Microsoft YaHei";
        const double DEFAULT_TEXT_WIDTH_SPACE_MULTIPLE = 2;
        const double DEFAULT_TEXT_HEIGHT_SPACE_MULTIPLE = 8;
        static Brush DEFAULT_FOREGROUND = new SolidColorBrush(Color.FromArgb(100, 100, 100, 100));

        private double mHeight;
        private double mWidth;
        private double mTextWidth;

        static WatermarkCanvas()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(WatermarkCanvas), new FrameworkPropertyMetadata(typeof(WatermarkCanvas)));
        }

        public static readonly DependencyProperty WatermarkTextProperty = DependencyProperty.Register("WatermarkText", typeof(string), typeof(WatermarkCanvas), new FrameworkPropertyMetadata(DEFAULT_TEXT));
        public static readonly DependencyProperty WatermarkFontSizeProperty = DependencyProperty.Register("WatermarkFontSize", typeof(double), typeof(WatermarkCanvas), new FrameworkPropertyMetadata(DEFAULT_FONT_SIZE));
        public static readonly DependencyProperty WatermarkFontFamilyProperty = DependencyProperty.Register("WatermarkFontFamily", typeof(string), typeof(WatermarkCanvas), new FrameworkPropertyMetadata(DEFAULT_FONT_FAMILY));
        public static readonly DependencyProperty WatermarkForegroundProperty = DependencyProperty.Register("WatermarkForeground", typeof(Brush), typeof(WatermarkCanvas), new FrameworkPropertyMetadata(DEFAULT_FOREGROUND));
        public static readonly DependencyProperty WatermarkTextWidthSpaceMultipleProperty = DependencyProperty.Register("WatermarkTextWidthSpaceMultiple", typeof(double), typeof(WatermarkCanvas), new FrameworkPropertyMetadata(DEFAULT_TEXT_WIDTH_SPACE_MULTIPLE));
        public static readonly DependencyProperty WatermarkTextHeightSpaceMultipleProperty = DependencyProperty.Register("WatermarkTextHeightSpaceMultiple", typeof(double), typeof(WatermarkCanvas), new FrameworkPropertyMetadata(DEFAULT_TEXT_HEIGHT_SPACE_MULTIPLE));
        public static readonly DependencyProperty WatermarkAngleProperty = DependencyProperty.Register("WatermarkAngle", typeof(double), typeof(WatermarkCanvas), new FrameworkPropertyMetadata(DEFAULT_ROTATE_ANGLE));

        public WatermarkCanvas()
        {
            InitDefaultParams();
        }

        #region Init

        private void InitDefaultParams()
        {
            this.IsHitTestVisible = false;
        }

        #endregion

        protected override void OnRender(DrawingContext drawingContext)
        {
            InitSizeParams();
            DrawTexts(drawingContext);
        }
        /// <summary>
        /// init the all kinds of size params
        /// </summary>
        private void InitSizeParams()
        {
            mWidth = this.ActualWidth;
            mHeight = this.ActualHeight;
            // 文字宽度，此处算出宽度后，后面乘了个列之间的宽度
            mTextWidth = MeasureTextWidth(WatermarkText, WatermarkFontSize, WatermarkFontFamily) * (1 + WatermarkTextWidthSpaceMultiple);
        }
        /// <summary>
        /// draw the watermark text
        /// </summary>
        /// <param name="drawingContext"></param>
        private void DrawTexts(DrawingContext drawingContext)
        {
            // rotate 旋转
            drawingContext.PushTransform(new RotateTransform(WatermarkAngle, 0, 0));
            FormattedText ft = new FormattedText(WatermarkText,
                        CultureInfo.InvariantCulture,
                        FlowDirection.LeftToRight,
                        new Typeface(WatermarkFontFamily),
                        WatermarkFontSize, WatermarkForeground);
            // calculate the the text's row and column number 根据文字宽高、布局宽高，计算要画多少个水印字
            int rowNumber = (int)(mHeight / WatermarkFontSize / 10) + 5;
            int columnNumber = (int)(mWidth / mTextWidth) + 2;
            // draw text 写字
            for (int row = -5; row < rowNumber; row++)
            {
                for (int column = -1; column < columnNumber; column++)
                {
                    // Stagger adjacent rows
                    double offset = row % 2 == 0 ? 0 : mTextWidth / 2;
                    Point point = new Point(mTextWidth * column - offset, WatermarkFontSize * row * WatermarkTextHeightSpaceMultiple);
                    drawingContext.DrawText(ft, point);
                }
            }
        }

        private double MeasureTextWidth(string text, double fontSize, string fontFamily)
        {
            FormattedText formattedText = new FormattedText(
                text,
                System.Globalization.CultureInfo.InvariantCulture,
                FlowDirection.LeftToRight,
                new Typeface(fontFamily),
                fontSize,
                Brushes.Black
            );
            return formattedText.WidthIncludingTrailingWhitespace;
        }

        #region CustomProperty
        /// <summary>
        /// 水印内容
        /// </summary>
        public string WatermarkText
        {
            get { return (string)this.GetValue(WatermarkTextProperty); }
            set { this.SetValue(WatermarkTextProperty, value);}
        }
        /// <summary>
        /// 水印内容
        /// </summary>
        public double WatermarkFontSize
        {
            get {
                return (double)this.GetValue(WatermarkFontSizeProperty); 
            }
            set { this.SetValue(WatermarkFontSizeProperty, value); }
        }
        /// <summary>
        /// 水印字体
        /// </summary>
        public string WatermarkFontFamily
        {
            get
            {
                return (string)this.GetValue(WatermarkFontFamilyProperty);
            }
            set { this.SetValue(WatermarkFontFamilyProperty, value); }
        }
        /// <summary>
        /// 水印颜色
        /// </summary>
        public Brush WatermarkForeground
        {
            get
            {
                return (Brush)this.GetValue(WatermarkForegroundProperty);
            }
            set { this.SetValue(WatermarkForegroundProperty, value); }
        }
        /// <summary>
        /// 水印水平间距的倍数
        /// </summary>
        public double WatermarkTextWidthSpaceMultiple
        {
            get
            {
                return (double)this.GetValue(WatermarkTextWidthSpaceMultipleProperty);
            }
            set { this.SetValue(WatermarkTextWidthSpaceMultipleProperty, value); }
        }
        /// <summary>
        /// 水印垂直间距的倍数
        /// </summary>
        public double WatermarkTextHeightSpaceMultiple
        {
            get
            {
                return (double)this.GetValue(WatermarkTextHeightSpaceMultipleProperty);
            }
            set { this.SetValue(WatermarkTextHeightSpaceMultipleProperty, value); }
        }
        /// <summary>
        /// 水印的旋转角度
        /// </summary>
        public double WatermarkAngle
        {
            get
            {
                return (double)this.GetValue(WatermarkAngleProperty);
            }
            set { this.SetValue(WatermarkAngleProperty, value); }
        }
        #endregion
    }
}
